/*
     Copyright 2007 Joseph M. Ferner

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System.Collections.Generic;
using System.Text;

namespace OpenServers.Net.Common.Utils {
    /// <summary>
    /// class to ease the creation and parsing of URLs.
    /// </summary>
    public class Url {
        private string _path;
        private string _anchor;
        private readonly IDictionary<string, IList<string>> _parameters = new Dictionary<string, IList<string>>();

        /// <summary>
        /// constructor.
        /// </summary>
        /// <param name="url">A full or relative url.</param>
        public Url(string url) {
            // get anchor
            int anchorToken = url.LastIndexOf('#');
            if (anchorToken >= 0) {
                Anchor = url.Substring(anchorToken + 1);
                url = url.Substring(0, anchorToken);
            }

            // get parameters
            int parameterToken = url.LastIndexOf('?');
            if (parameterToken >= 0) {
                string parameterString = url.Substring(parameterToken + 1);
                url = url.Substring(0, parameterToken);
                string[] parameters = parameterString.Split('&');
                foreach (string parameter in parameters) {
                    int endOfNameToken = parameter.IndexOf('=');
                    string name, value;
                    if (endOfNameToken >= 0) {
                        name = parameter.Substring(0, endOfNameToken);
                        value = parameter.Substring(endOfNameToken + 1);
                    } else {
                        name = parameter;
                        value = null;
                    }
                    AddParameter(name, value);
                }
            }

            // get path
            _path = url;
        }

        /// <summary>
        /// Adds a parameter.
        /// </summary>
        public void AddParameter(string name, string value) {
            if (_parameters.ContainsKey(name)) {
                _parameters[name].Add(value);
            } else {
                IList<string> valueList = new List<string>();
                valueList.Add(value);
                _parameters.Add(name, valueList);
            }
        }

        ///<summary>
        /// The path element of the url. after the host and port and before the parameters.
        ///</summary>
        public string Path {
            get { return _path; }
            set { _path = value; }
        }

        /// <summary>
        /// The anchor part of the url. This is the string after the '#'.
        /// </summary>
        public string Anchor {
            get { return _anchor; }
            set { _anchor = value; }
        }

        /// <summary>
        /// Returns the URL.
        /// </summary>
        public override string ToString() {
            StringBuilder result = new StringBuilder();

            // append path
            result.Append(Path);

            // append parameters
            if (_parameters.Count > 0) {
                result.Append("?");
                bool first = true;
                foreach (KeyValuePair<string, IList<string>> parameter in _parameters) {
                    foreach (string value in parameter.Value) {
                        if (!first) {
                            result.Append("&");
                        }
                        result.AppendFormat("{0}={1}", parameter.Key, value);
                        first = false;
                    }
                }
            }

            // append anchor
            if (Anchor != null) {
                result.Append("#");
                result.Append(Anchor);
            }

            return result.ToString();
        }
    }
}